﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
using MaxZhang.EasyEntities.Attribute;
using MaxZhang.EasyEntities.Dynamic.Aop.Exception;

namespace MaxZhang.EasyEntities.Dynamic.Aop
{
    /// <summary>
    /// AOP拦截器表
    /// </summary>
    public class AopTabel
    {
        private static object lockObject = new object();
        private static volatile AopTabel m_instance = null;

        private AopTabel()
        {
            _classList = new List<AopClassInfo>(10);

        }

        //Singleton
        public static AopTabel Aspects
        {
            get
            {
                lock (lockObject)
                {
                    if (m_instance == null)
                    {

                        m_instance = new AopTabel();

                    }

                    return m_instance;
                }
            }
        }

        private List<AopClassInfo> _classList;

        public List<AopClassInfo> ClassList
        {
            get
            {
                return _classList;
            }
        }


        /// <summary>
        /// 添加类型信息
        /// </summary>
        /// <param name="name">类名</param>
        public bool AddClassInfo(string name)
        {
            var item = GetClassInfoByName(name);

            if (item != null)
                return false;

            _classList.Add(new AopClassInfo(name));
            return true;
        }

        /// <summary>
        /// 删除类型信息
        /// </summary>
        /// <param name="name">类名</param>
        public bool RemoveClassInfo(string name)
        {
            var item = GetClassInfoByName(name);
           
            if (item == null)
               return false;

          return _classList.Remove(item);
        }

        /// <summary>
        /// 得到指定名称的类型信息
        /// </summary>
        /// <param name="name">类型名称</param>
        /// <returns>类型信息</returns>
        public AopClassInfo GetClassInfoByName(string name)
        {
            var item = (from c in _classList
                        where c.Name.Equals(name)
                        select c).FirstOrDefault();

            return item;
        }


        /// <summary>
        /// 在AopTable中得到指定类名和方法名的所有拦截器
        /// </summary>
        /// <param name="classname">类名</param>
        /// <param name="method">方法名</param>
        /// <returns>拦截器数组</returns>
        public InterceptorBaseAttribute[] GetInterceptors(string classname, string method)
        {
            List<InterceptorBaseAttribute> interceptors = new List<InterceptorBaseAttribute>();
            var cItem=  GetClassInfoByName(classname);
            if (cItem == null)
                return interceptors.ToArray();
            var mItem= cItem.GetMethodInfoByName(method);
            if (mItem == null)
                return interceptors.ToArray();
           
            var apectList= mItem.GetAllGetAspectInfo();
            foreach (var apect in apectList)
            {
                interceptors.Add(apect.Interceptor);
            }
            return interceptors.ToArray();
        }





        /// <summary>
        /// 添加拦截器
        /// </summary>
        /// <param name="interceptor">拦截器对象</param>
        public void Add(AopInterceptor interceptor)
        {
            string className = interceptor.ClassName.FullName;
            
            foreach(var item in interceptor.AspectList)
            {
                this.Add(className, interceptor.MethodName, item);
            }
        }



        /// <summary>
        /// 添加拦截器
        /// </summary>
        /// <param name="classname">类名</param>
        /// <param name="methodname">方法名</param>
        /// <param name="aectinfo">切面信息</param>
        public void Add(string classname,string methodname,AopAspectInfo aectinfo)
        {
            var citem = GetClassInfoByName(classname);
            if(citem!=null)  //有这个类型
            {
                var mitem = citem.GetMethodInfoByName(methodname);
                if (mitem!=null)    //有此方法信息
                {
                    mitem.AspectList.Add(aectinfo);
                }
                else                //没有方法信息
                {
                    var newMitem = new AopMethodInfo(methodname);
                    citem.MethodList.Add(newMitem);
                    newMitem.AspectList.Add(aectinfo);
                }
 
            }
            else           //没有类型
            {
                var newCitem = new AopClassInfo(classname);
                var mitem = newCitem.GetMethodInfoByName(methodname);
                if (mitem != null)    //有此方法信息
                {
                    mitem.AspectList.Add(aectinfo);
                }
                else                //没有方法信息
                {
                    var newMitem = new AopMethodInfo(methodname);
                    newCitem.MethodList.Add(newMitem);
                    newMitem.AspectList.Add(aectinfo);
                    this.ClassList.Add(newCitem);
                }
            }

        }

        /// <summary>
        /// 清理所有拦截器
        /// </summary>
        public void Clear()
        {
           foreach (var c in this._classList)
           {
               
               foreach (var m in c.MethodList)
               {
                   m.AspectList.Clear();
               }
               c.MethodList.Clear();
           }
            this._classList.Clear();

        }

        /// <summary>
        /// 从文件中加载拦截器
        /// </summary>
        /// <param name="filename"></param>
        public static void LoadFile(string filename)
        {
            Assembly assembly = Assembly.GetCallingAssembly();    //(web)主程序的程序集
            
            if (File.Exists(filename))
            {
                var c = new Config(filename, assembly);
                c.Load();
            }
            else
                throw new AopConfigException("没有找到配置文件!");
        }


    
    }
}
